/**********************************************************************************************************
** 驱动文件：	ptkt-AC100.c
** 驱动类型：	ptkt
** 设备名称：	普通空调监控
** 设备型号：	AC100
** 设备品牌：	融智云
** 设备协议：	Modbus-EX
** 驱动描述：	RS-485网络型空调远程红外遥控器是一款万能型遥控器，具备多品牌多型号空调控制指令。同时具有红外指令学习、来电自启动、空调运行状态检测等多种功能，通过RS485联网可以实现远程开关机、设置温度、设置运行模式等多种功能。
** 生成日期：	2019-04-10 12:11:36
**********************************************************************************************************/
#include "Includes.h"


/**********************************************************************************************************
* 定义设备数据点变量结构
**********************************************************************************************************/
typedef struct{
	Var temperature;							//环境温度
	Var humidity;								//环境湿度
	Var acRunStatus;							//运行状态
	Var irRemoteStatus;							//红外状态
	Var irRemoteMode;							//遥控器模式
	Var irRemoteID;								//遥控器配对ID
	Var acPower;								//开机/关机
	Var acMode;									//运行模式
	Var acTemperature;							//设定温度
	Var acWindSpeed;							//设定风速
	Var acWindDir;								//设定风向
	Var signalType;								//运行信号类型
	Var signal;									//运行信号值
	Var signalThreshold;						//运行信号阀值
	Var autoControlEnable;						//自动控制使能
}Data_Struct;									//定义变量结构


/**********************************************************************************************************
* 设备数据点变量属性声明
**********************************************************************************************************/
const static Var_Property_Def var_attr[] = {
	{
		FLOAT,
		0,
		READONLY,
		"temperature",
		"环境温度",
		"℃",
		"当前环境温度",
		1,
		0,
		"当前环境温度过高",
		"当前环境温度过低",
		35,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"humidity",
		"环境湿度",
		"%",
		"当前环境湿度",
		1,
		0,
		"当前环境湿度过高",
		"当前环境湿度过低",
		75,
		15
	},
	{
		OCTSTR,
		0,
		READONLY,
		"acRunStatus",
		"运行状态",
		"",
		"空调当前状态：0-空调停机，1-空调工作",
		0,
		0,
		"空调停机",
		"",
		0,
		0
	},
	{
		OCTSTR,
		0,
		READONLY,
		"irRemoteStatus",
		"红外状态",
		"",
		"红外学习或发射状态：0-空闲；1-工作",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		INTEGER,
		0,
		READWRITE,
		"irRemoteMode",
		"遥控器模式",
		"",
		"红外遥控器模式：0-红外指令学习模式，1-学习型遥控器模式，2-遥控器配对模式，3-万能遥控器模式",
		0,
		0,
		"",
		"",
		3,
		0
	},
	{
		INTEGER,
		0,
		READWRITE,
		"irRemoteID",
		"遥控器配对ID",
		"",
		"遥控器配对ID",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		BOOLEAN,
		0,
		READWRITE,
		"acPower",
		"开机/关机",
		"",
		"空调开关控制：0-关机，1-开机",
		0,
		0,
		"",
		"",
		1,
		0
	},
	{
		INTEGER,
		0,
		READWRITE,
		"acMode",
		"运行模式",
		"",
		"空调运行模式：0-自动，1-制冷，2-制热，3-除湿，4-送风",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		INTEGER,
		0,
		READWRITE,
		"acTemperature",
		"设定温度",
		"℃",
		"设定空调温度，范围16~30℃",
		0,
		0,
		"",
		"",
		20,
		0
	},
	{
		INTEGER,
		0,
		READWRITE,
		"acWindSpeed",
		"设定风速",
		"",
		"空调风速设定：0-自动，1-低，2-中，3-高",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		BOOLEAN,
		0,
		READWRITE,
		"acWindDir",
		"设定风向",
		"",
		"空调风向设定：0-扫风关闭，1-扫风开启",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		OCTSTR,
		0,
		READONLY,
		"signalType",
		"运行信号类型",
		"",
		"运行监测信号类型：0-电流信号，1-光电信号",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		INTEGER,
		0,
		READONLY,
		"signal",
		"运行信号值",
		"",
		"运行信号值",
		0,
		0,
		"空调工作",
		"空调停机",
		9999,
		0.05
	},
	{
		INTEGER,
		0,
		READWRITE,
		"signalThreshold",
		"运行信号阀值",
		"",
		"空调运行信号阀值，用于判断空调工作和停机",
		0,
		0,
		"",
		"",
		3000,
		0
	},
	{
		BOOLEAN,
		0,
		READWRITE,
		"autoControlEnable",
		"自动控制使能",
		"",
		"自动控制使能，用于空调关机自启动，高温自启动，0-禁用，1-启用",
		0,
		0,
		"",
		"",
		1,
		0
	}
};


/**********************************************************************************************************
* 函数名称： static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
* 函数说明： 生成获取传感器数据指令
* 输入参数： 指令索引，传感器地址，变量结构体指针,以及指令缓存区指针,指令长度
* 返回参数： 无
**********************************************************************************************************/
static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
{
	Data_Struct 	*d = (Data_Struct*)data;
	unsigned int	temp;
	if(d->acTemperature.value.inum>30) d->acTemperature.value.inum = 30;
	if(d->acTemperature.value.inum<16) d->acTemperature.value.inum = 16;

	switch(index)
	{
		//获取红外控制器状态
		case 0:
			cmd[0] = 0xA5;
			cmd[1] = 0x02;
			cmd[2] = (addr>>8)&0x00FF;			
			cmd[3] = addr&0x00FF;
			cmd[4] = 0x04;
			cmd[5] = 0x00;								
			cmd[6] = 0x00;
			cmd[7] = 0x00;	
			cmd[8] = 0x12;
			*len = CRC16_Padding(cmd, 9);
			break;
		//下发阀值和自动控制使能指令
		case 1:
			if(d->autoControlEnable.status==NewSet||d->signalThreshold.status==NewSet){
				cmd[0] = 0xA5;
				cmd[1] = 0x02;
				cmd[2] = (addr>>8)&0x00FF;
				cmd[3] = addr&0x00FF;
				cmd[4] = 0x10;
				cmd[5] = 0x00;
				cmd[6] = 0x0A;
				cmd[7] = 0x00;
				cmd[8] = 0x02;
				cmd[9] = 0x04;
				cmd[10]= (d->signalThreshold.value.inum>>8)&0x00FF;
				cmd[11]= d->signalThreshold.value.inum&0x00FF;
				cmd[12]= 0x00;
				cmd[13]= d->autoControlEnable.value.inum;
				*len = CRC16_Padding(cmd, 14);
			}
			else{
				*len  = -1;
			}
			break;
		//修改遥控器模式和万能遥控器ID
		case 2:
			if(d->autoControlEnable.status==Normal&&d->signalThreshold.status==Normal){	//如果设置失败停止之后的指令发送
				if(d->irRemoteMode.status || d->irRemoteID.status){
					cmd[0] = 0xA5;
					cmd[1] = 0x02;
					cmd[2] = (addr>>8)&0x00FF;			
					cmd[3] = addr&0x00FF;
					cmd[4] = 0x10;
					cmd[5] = 0x00;								
					cmd[6] = 0x02;
					cmd[7] = 0x00;	
					cmd[8] = 0x03;
					cmd[9] = 0x06;
					temp   = (unsigned int)d->irRemoteID.value.inum;
					cmd[10]= (temp>>8)&0x00FF;
					cmd[11]= temp&0x00FF;	
					cmd[12]= (temp>>24)&0x00FF;
					cmd[13]= (temp>>16)&0x00FF;	
					cmd[14]= 0x00;
					cmd[15]= d->irRemoteMode.value.inum;		
					*len = CRC16_Padding(cmd, 16);
				}
				else{
					*len  = -1;
				}	
			}
			break;
		//修改遥控器模式和万能遥控器ID
		case 3:
			if(d->irRemoteMode.status || d->irRemoteID.status){
				cmd[0] = 0xA5;
				cmd[1] = 0x02;
				cmd[2] = (addr>>8)&0x00FF;			
				cmd[3] = addr&0x00FF;
				cmd[4] = 0x10;
				cmd[5] = 0x00;								
				cmd[6] = 0x02;
				cmd[7] = 0x00;	
				cmd[8] = 0x03;
				cmd[9] = 0x06;
				temp   = (unsigned int)d->irRemoteID.value.inum;
				cmd[10]= (temp>>8)&0x00FF;
				cmd[11]= temp&0x00FF;	
				cmd[12]= (temp>>24)&0x00FF;
				cmd[13]= (temp>>16)&0x00FF;
				cmd[14]= 0x00;
				cmd[15]= d->irRemoteMode.value.inum;		
				*len = CRC16_Padding(cmd, 16);
			}
			else{
				*len  = -1;
			}			
			break;
		//下发控制
		case 4:
			if(d->acPower.status==NewSet || d->acMode.status==NewSet || d->acTemperature.status==NewSet || d->acWindSpeed.status==NewSet || d->acWindDir.status==NewSet){
				cmd[0] = 0xA5;
				cmd[1] = 0x02;
				cmd[2] = (addr>>8)&0x00FF;			
				cmd[3] = addr&0x00FF;
				cmd[4] = 0x10;
				cmd[5] = 0x00;								
				cmd[6] = 0x05;
				cmd[7] = 0x00;	
				cmd[8] = 0x05;
				cmd[9] = 0x0A;	
				cmd[10]= 0x00;
				cmd[11]= d->acPower.value.inum;
				cmd[12]= 0x00;
				cmd[13]= d->acMode.value.inum;
				cmd[14]= 0x00;
				cmd[15]= d->acTemperature.value.inum;
				cmd[16]= 0x00;
				cmd[17]= d->acWindSpeed.value.inum;
				cmd[18]= 0x00;
				cmd[19]= d->acWindDir.value.inum;
				*len = CRC16_Padding(cmd, 20);
			}
			else{
				*len  = -1;
			}
			break;
		default:
			break;
	}
}


/**********************************************************************************************************
* 函数名称： static int parse_fun(short index, int addr, void *data, char *buf, short len)
* 函数说明： 解析传感器响应的数据，并写入数据库
* 输入参数： 解析索引,传感器地址，变量结构体指针，以及响应数据缓存取指针，响应数据长度
* 返回参数： 返回解析结果，返回0成功，返回1失败
**********************************************************************************************************/
static int parse_fun(short index, int addr, void *data, char *buf, short len)
{
	union{
		short 			dat16;
      	unsigned char  	dat8[2];
    }DAT16_8;						   //数据类型转换
	Data_Struct 	*d = (Data_Struct*)data;
	unsigned char	*buffer = (unsigned char*)buf;
	if(buf!=NULL && len>=8 && buffer[0]==0xA5 && buffer[1]==0x02 && addr==((buffer[2]<<8) + buffer[3]))
	{	
		if(CRC16_Check(buf,len))
		{	
			switch(index){
				case 0:
					DAT16_8.dat8[1] = buffer[6];
					DAT16_8.dat8[0] = buffer[7];
					d->temperature.value.fnum = DAT16_8.dat16*0.01;
					DAT16_8.dat8[1] = buffer[8];
					DAT16_8.dat8[0] = buffer[9];
					d->humidity.value.fnum = DAT16_8.dat16*0.01;

					d->signalType.value.str = buffer[11]==1?"光电信号":"电流信号";
				
					DAT16_8.dat8[1] = buffer[12];
					DAT16_8.dat8[0] = buffer[13];
					d->signal.value.inum = DAT16_8.dat16;
				
//					if(buffer[11]==1){
//						d->signal.value.fnum = DAT16_8.dat16*1.0;
//					}
//					else{
//						d->signal.value.fnum = DAT16_8.dat16*0.001;
//					}
					

					d->acRunStatus.value.str = buffer[15]==1?"空调工作":"空调停机";
					Set_Var_Status(&d->acRunStatus,	buffer[15]==1?Normal:Alarm, NULL);

					d->irRemoteStatus.value.str = buffer[17]?"工作":"空闲";
					
					if(d->autoControlEnable.status==NewSet&&d->signalThreshold.status==NewSet){
						d->acPower.status			= Normal;
						d->acMode.status			= Normal;
						d->acTemperature.status		= Normal;
						d->acWindSpeed.status		= Normal;
						d->acWindDir.status			= Normal;
						
						d->signalThreshold.status	= Normal;
						d->autoControlEnable.status	= Normal;
						
						d->acPower.value.inum		= buffer[29];
						d->acMode.value.inum		= buffer[31];
						d->acTemperature.value.inum = buffer[33];
						d->acWindSpeed.value.inum	= buffer[35];
						d->acWindDir.value.inum		= buffer[37];
						
						DAT16_8.dat8[1] 			= buffer[38];
						DAT16_8.dat8[0] 			= buffer[39];
						d->signalThreshold.value.inum	= DAT16_8.dat16;
						d->autoControlEnable.value.inum	= buffer[41];						

						d->irRemoteID.value.inum	= (buffer[24]<<24)|(buffer[25]<<16)|(buffer[22]<<8)|buffer[23];
						d->irRemoteMode.value.inum	= buffer[27];						
					}
					break;
				case 1:
					if(buffer[4]==0x10&&buffer[5]==0x00&&buffer[6]==0x0A&&buffer[7]==0x00&&buffer[8]==0x02){
						d->signalThreshold.status	= Normal;
						d->autoControlEnable.status	= Normal;
					}
					break;
				case 2:
				case 3:					
					if(buffer[4]==0x10&&buffer[5]==0x00&&buffer[6]==0x02&&buffer[7]==0x00&&buffer[8]==0x03){
						d->irRemoteMode.status		= Normal;
						d->irRemoteID.status		= Normal;
					}
					break;					
				case 4:
					if(buffer[4]==0x10&&buffer[5]==0x00&&buffer[6]==0x05&&buffer[7]==0x00&&buffer[8]==0x05){
						d->acPower.status			= Normal;
						d->acMode.status			= Normal;
						d->acTemperature.status		= Normal;
						d->acWindSpeed.status		= Normal;
						d->acWindDir.status			= Normal;
					}
					break;
				default:
					break;
			}
			return 0;		
		}
	}
	return 1;
}


/**********************************************************************************************************
* 函数名称： void ptkt_AC100_Registration(void)
* 函数说明： 普通空调监控驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void ptkt_AC100_Registration(void)
{
	DeviceDriverRegistration(
		"ptkt",													//设备类型
		"普通空调监控",											//设备名称（导航栏默认显示名称）
		"融智云",												//设备品牌
		"AC100",												//设备型号
		"RS-485网络型空调远程红外遥控器是一款万能型遥控器，具备多品牌多型号空调控制指令。同时具有红外指令学习、来电自启动、空调运行状态检测等多种功能，通过RS485联网可以实现远程开关机、设置温度、设置运行模式等多种功能。",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		200														//设备响应超时时间
	);	
}

/**********************************************************************************************************
* 函数名称： void ptkt_AC100F1_Registration(void)
* 函数说明： 普通空调监控驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void ptkt_AC100F1_Registration(void)
{
	DeviceDriverRegistration(
		"ptkt",													//设备类型
		"一层空调监控",											//设备名称（导航栏默认显示名称）
		"融智云",												//设备品牌
		"AC100F1",												//设备型号
		"RS-485网络型空调远程红外遥控器是一款万能型遥控器，具备多品牌多型号空调控制指令。同时具有红外指令学习、来电自启动、空调运行状态检测等多种功能，通过RS485联网可以实现远程开关机、设置温度、设置运行模式等多种功能。",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		200														//设备响应超时时间
	);	
}

/**********************************************************************************************************
* 函数名称： void ptkt_AC100F2_Registration(void)
* 函数说明： 普通空调监控驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void ptkt_AC100F2_Registration(void)
{
	DeviceDriverRegistration(
		"ptkt",													//设备类型
		"二层空调监控",											//设备名称（导航栏默认显示名称）
		"融智云",												//设备品牌
		"AC100F2",												//设备型号
		"RS-485网络型空调远程红外遥控器是一款万能型遥控器，具备多品牌多型号空调控制指令。同时具有红外指令学习、来电自启动、空调运行状态检测等多种功能，通过RS485联网可以实现远程开关机、设置温度、设置运行模式等多种功能。",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		200														//设备响应超时时间
	);	
}

/**********************************************************************************************************
* 函数名称： void ptkt_AC100F3_Registration(void)
* 函数说明： 普通空调监控驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void ptkt_AC100F3_Registration(void)
{
	DeviceDriverRegistration(
		"ptkt",													//设备类型
		"三层空调监控",											//设备名称（导航栏默认显示名称）
		"融智云",												//设备品牌
		"AC100F3",												//设备型号
		"RS-485网络型空调远程红外遥控器是一款万能型遥控器，具备多品牌多型号空调控制指令。同时具有红外指令学习、来电自启动、空调运行状态检测等多种功能，通过RS485联网可以实现远程开关机、设置温度、设置运行模式等多种功能。",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		200														//设备响应超时时间
	);	
}

/**********************************************************************************************************
* 函数名称： void ptkt_AC100F4_Registration(void)
* 函数说明： 普通空调监控驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void ptkt_AC100F4_Registration(void)
{
	DeviceDriverRegistration(
		"ptkt",													//设备类型
		"四层空调监控",											//设备名称（导航栏默认显示名称）
		"融智云",												//设备品牌
		"AC100F4",												//设备型号
		"RS-485网络型空调远程红外遥控器是一款万能型遥控器，具备多品牌多型号空调控制指令。同时具有红外指令学习、来电自启动、空调运行状态检测等多种功能，通过RS485联网可以实现远程开关机、设置温度、设置运行模式等多种功能。",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		200														//设备响应超时时间
	);	
}

/**********************************************************************************************************
* 函数名称： void ptkt_AC100F5_Registration(void)
* 函数说明： 普通空调监控驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void ptkt_AC100F5_Registration(void)
{
	DeviceDriverRegistration(
		"ptkt",													//设备类型
		"五层空调监控",											//设备名称（导航栏默认显示名称）
		"融智云",												//设备品牌
		"AC100F5",												//设备型号
		"RS-485网络型空调远程红外遥控器是一款万能型遥控器，具备多品牌多型号空调控制指令。同时具有红外指令学习、来电自启动、空调运行状态检测等多种功能，通过RS485联网可以实现远程开关机、设置温度、设置运行模式等多种功能。",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		200														//设备响应超时时间
	);	
}

/**********************************************************************************************************
* 函数名称： void ptkt_AC100F6_Registration(void)
* 函数说明： 普通空调监控驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void ptkt_AC100F6_Registration(void)
{
	DeviceDriverRegistration(
		"ptkt",													//设备类型
		"六层空调监控",											//设备名称（导航栏默认显示名称）
		"融智云",												//设备品牌
		"AC100F6",												//设备型号
		"RS-485网络型空调远程红外遥控器是一款万能型遥控器，具备多品牌多型号空调控制指令。同时具有红外指令学习、来电自启动、空调运行状态检测等多种功能，通过RS485联网可以实现远程开关机、设置温度、设置运行模式等多种功能。",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		200														//设备响应超时时间
	);	
}
